package models

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"
)

func (rt *RunTime) 命令行控制(话语 string) {
	var err error
	sp := strings.Split(话语, " ")
	switch sp[0] {
	case "问题":
		if len(sp[0]) == 1 {
			rt.消息_系统消息(3, "正确格式为: /问题 问题描述")
			return
		}
		//连接
		conn, err := net.Dial("tcp", "www.kaixuanguilai.com:2285") //连接TCP
		if err != nil {
			rt.消息_系统消息(3, "远程服务器连接失败")
			return
		}
		defer conn.Close()
		conn.Write([]byte("postmsg\n" + UTF8ToGBK(rt.V角色.V名字) + "\n" + UTF8ToGBK(话语[3:])))
		rt.消息_系统消息(3, "问题已上报")
	case "角色信息":
		rt.消息_系统消息(3, fmt.Sprintf("角色名称[%s]ID[%d] X[%d] Y[%d] Z[%d] 攻击速度[%f] ", rt.V角色.V名字, rt.V角色内容.Id, rt.V角色内容.X, rt.V角色内容.Y, rt.V角色内容.Z, rt.V角色内容.V基础属性[E基础属性_攻击速度]))
	case "召唤":
		if rt.角色_是否管理员() == false {
			rt.消息_系统消息(3, "不可识别的指令")
			return
		}
		rt.执行脚本("/"+话语, rt.V角色内容.Id)
	case "ItemUse":
		if len(sp) != 3 {
			rt.消息_系统消息(3, "指令错误")
			return
		}
		var 位置X, 位置Y uint8
		if t, err := strconv.Atoi(sp[1]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			位置X = uint8(t)
		}
		if t, err := strconv.Atoi(sp[2]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			位置Y = uint8(t)
		}
		rt.背包_双击背包中的一格(0, 位置X, 位置Y)
	case "ItemUseSub":
		if len(sp) != 4 {
			rt.消息_系统消息(3, "指令错误")
			return
		}
		var 位置X, 位置Y uint8
		var 背包ID uint8
		if t, err := strconv.Atoi(sp[1]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			位置X = uint8(t)
		}
		if t, err := strconv.Atoi(sp[2]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			位置Y = uint8(t)
		}
		if t, err := strconv.Atoi(sp[3]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			背包ID = uint8(t)
		}
		rt.背包_双击背包中的一格(背包ID, 位置X, 位置Y)
	case "ItemApply", "ItemApplySub": //两个物品合一
		var 背包ID uint8
		if sp[0] == "ItemApply" {
			背包ID = 0
		} else if t, err := strconv.Atoi(sp[5]); err == nil {
			背包ID = uint8(t)
		} else {
			rt.消息_系统消息(3, "指令错误1")
		}
		/*if len(sp) < 7 { //平常的都是5个，超凯是6个
			rt.消息_系统消息(3, "指令错误")
			return
		}*/
		var 宝石X, 宝石Y, 物品X, 物品Y uint8
		if t, err := strconv.Atoi(sp[1]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			宝石X = uint8(t)
		}
		if t, err := strconv.Atoi(sp[2]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			宝石Y = uint8(t)
		}
		if t, err := strconv.Atoi(sp[3]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			物品X = uint8(t)
		}
		if t, err := strconv.Atoi(sp[4]); err != nil {
			rt.消息_系统消息(3, "指令错误")
			return
		} else {
			物品Y = uint8(t)
		}
		背包 := rt.背包_获取背包(背包ID)
		宝石 := rt.背包_查询位置物品(背包, 宝石X, 宝石Y)
		if 宝石 == nil {
			rt.消息_系统消息(3, "不存在的宝石")
			return
		}
		宝石信息 := 物品_获取物品信息(宝石.V信息ID)
		//宝石属性 := m_基础属性[]
		if (宝石信息.V类型 != "Application") && (宝石信息.V类型 != "ApplicationSelect") {
			rt.消息_系统消息(3, "宝石错误")
			return
		}
		物品 := rt.背包_查询位置物品(背包, 物品X, 物品Y)
		if 物品 == nil {
			rt.消息_系统消息(3, "不存在的物品7")
			return
		}
		物品信息 := 物品_获取物品信息(物品.V信息ID)
		使用宝石 := false
		defer func() {
			if 使用宝石 == true {
				rt.背包_取出指定位置物品(背包, 宝石X, 宝石Y, 0)
				db.Where("id=?", 宝石.Id).Delete(宝石)
				defer func() {
					rt.同步_背包指定点(背包, 宝石X, 宝石Y, false)
				}()
			}
		}()
		宝石属性, ok := m_宝石属性[宝石.V中文名称]
		if ok == false {
			rt.消息_系统消息(3, "此物品没有设置升级属性")
			return
		}
		已有属性个数 := 砸宝_获取物品属性个数(物品)
		if (rt.V角色.V等级 < 宝石属性.V角色等级下限) || (rt.V角色.V等级 > 宝石属性.V角色等级上限) {
			rt.消息_系统消息(3, fmt.Sprintf("此宝石要求人物等级在%d级至%d之间", 宝石属性.V角色等级下限, 宝石属性.V角色等级上限))
			return
		}
		if (已有属性个数 < 宝石属性.V属性个数下限) || (已有属性个数 > 宝石属性.V属性个数上限) {
			rt.消息_系统消息(3, fmt.Sprintf("此宝石要求物品属性数量 在%d和%d之间", 宝石属性.V属性个数下限, 宝石属性.V属性个数上限))
			return
		}
		if (物品信息.V等级 < 宝石属性.V物品等级下限) || (物品信息.V等级 > 宝石属性.V物品等级上限) {
			rt.消息_系统消息(3, fmt.Sprintf("此宝石要求物品等级在%d与%d之间", 宝石属性.V物品等级下限, 宝石属性.V物品等级上限))
			return
		}
		if 物品信息.V穿戴位置&宝石属性.V物品掩码 == 0 {
			rt.消息_系统消息(3, "此宝石不能升级此物品")
		}

		if 宝石属性.V是否会删除属性 == true {
			使用宝石 = true
			if 砸宝_随机删除一个属性(物品) == true {
				rt.消息_系统消息(3, "消失属性!")
			}
		}
		if 宝石属性.V是否会添加属性 == true {
			使用宝石 = true
			if 砸宝_随机添加一个属性(物品) == false {
				rt.消息_系统消息(3, "无变化")
			} else {
				rt.消息_系统消息(3, "添加属性成功")
			}
		}
		if 宝石属性.V是否升级属性 == true {
			选择的属性 := -1
			if 宝石属性.V是否选择属性升级 == true {
				if t, err := strconv.Atoi(sp[6]); err != nil {
					rt.消息_系统消息(3, "选择的属性无效!")
					return
				} else {
					选择的属性 = t
				}
			}
			使用宝石 = true
			switch 砸宝_升级一个属性(物品, 选择的属性) {
			case 0:
				rt.消息_系统消息(3, "无变化")
			case 1:
				物品, err = rt.背包_取出指定位置物品(背包, 物品X, 物品Y, 0)
				if err != nil {
					panic("~~")
				}
				db.Where("id=?", 物品.Id).Delete(物品)
				rt.同步_背包指定点(背包, 物品X, 物品Y, false)
				rt.消息_系统消息(3, "物品消失")
				return
			case 2:
				rt.消息_系统消息(3, "属性升级")
			}
		}
		//开始对改动过的装备进行刷新
		老颜色 := 物品.V名称颜色
		if 物品信息.V等级 == 11 {
			物品.V名称颜色 = 2 //设置为金色颜色
		} else if 物品信息.V等级 >= 12 {
			物品.V名称颜色 = 3 //设置为金色颜色
		} else {
			switch 砸宝_获取物品属性个数(物品) {
			case 0:
			case 1, 2:
				物品.V名称颜色 = 1 //设置为魔法颜色
			case 3, 4:
				物品.V名称颜色 = 2 //设置为金色颜色
			}
		}
		if 老颜色 != 物品.V名称颜色 {
			物品.Stata.V更新字段["V名称颜色"] = true
		}
		rt.同步_背包指定点(背包, 物品X, 物品Y, true)
	case "升级":
		if rt.角色_是否管理员() == false {
			rt.消息_系统消息(3, "不可识别的指令")
			return
		}
		升几级 := 1
		if len(sp) == 2 {
			if t, err := strconv.Atoi(sp[1]); err == nil {
				升几级 = t
			}
		}
		for i := 0; i < 升几级; i++ {
			rt.角色升级()
		}
	case "动作":
		if len(sp) != 4 {
			rt.消息_系统消息(3, "移动失败 正确指令:/动作 名称 0 0")
			return
		}
		t0, _ := strconv.Atoi(sp[2])
		t1, _ := strconv.Atoi(sp[2])
		rt.动作_效果(sp[1], int32(t0), int32(t1))
	case "Bag Arrange": //整理背包
		rt.背包_整理(rt.背包_获取背包(0))
	default:
		if rt.角色_是否管理员() == false {
			rt.消息_系统消息(3, "不可识别的指令")
			return
		}
		if rt.执行脚本("/"+话语, rt.V角色内容.Id) == false {
			rt.消息_系统消息(3, fmt.Sprintf("未知指令:%s", 话语))
		}
	}
}
func 向周边发送消息(发送人 *StructMap, cmd byte, headlen int, tx []byte) {
	周边S := 发送人.V空间.F找到指定位置四周内容(发送人.X, 发送人.Y, m_可视距离, uint8(E类别_人物))
	for _, 内容 := range 周边S {
		if 内容.V准备好 == false {
			continue
		}
		if 内容.Id == 发送人.Id {
			continue
		}
		F地图_发送信息(内容, &S交换数据{
			V发送人: 发送人,
			V类型:  E交换数据类型_透传数据,
			V内容: S交换角色通讯{
				VCMD:     cmd,
				VHeadlen: headlen,
				V信息:      tx,
			},
		})
	}
}

/*
func (rt *RunTime) 消息_角色说话呼喊(说话 bool, 话语 string) {

	if rt.V角色内容.V是否死亡 == true {
		return
	}
	类型 := byte(1)
	if 说话 == false {
		类型 = 2
	}

	tx := CreateBuff(100)
	tx.AddInt32(rt.V角色内容.Id)
	tx.AddInt16(0x00C0)
	tx.AddByte(0x00)
	tx.AddByte(类型)
	tx.AddStringAndLen(rt.V角色.V名字)
	tx.AddStringAndLen(话语)
	rt.AddHeadSend10(0x0B, [][]byte{tx.Buff[:4], tx.Buff[4:]}) //先给自己发
	向周边发送消息(rt.V角色内容, 0x0B, 4, tx.Buff)

}*/

func (rt *RunTime) 消息_底部框显示文字(编码 int32, 话语 string) {
	tx := CreateBuff(2 + 4 + len(话语))
	tx.AddInt16(0x00BC)
	tx.AddInt32(编码)
	tx.AddStringAndLen(话语)
	rt.AddHeadSend10(0x0A, [][]byte{{}, tx.Buff})
}

func (rt *RunTime) 消息_系统消息(mode int32, msg string) {
	sp := strings.Split(msg, "\r\n")
	for _, s := range sp {
		if len(s) == 0 {
			continue
		}
		tx := CreateBuff(2 + 4 + 4 + len(s))
		tx.AddInt16(0xBC)
		tx.AddInt32(mode)
		tx.AddStringAndLen(s)
		rt.AddHeadSend10(0x0A, [][]byte{{}, tx.Buff})
	}
}
func 消息_系统消息(发给谁 *StructMap, mode int32, msg string) {
	if 发给谁.V类别 != E类别_人物 {
		return
	}
	go 发给谁.V内容附加.(*RunTime).消息_系统消息(mode, msg)
}

//02 暗黄色 ，左上，上面显示
//03  黄色，只在左边显示
//04 白色   只在上面显示
//05 黄色   方格的所有里面显示

//功能 游戏中各种通讯，由这里管理
func 系统_游戏电信服务() {
	for {
		select {
		case 电话, ok := <-m_电信服务:
			if ok == false {
				panic("电信服务不可用")
			}
			switch 电话.类型 {
			case E说话, E呼喊:
				说话方式 := byte(1)
				if 电话.类型 == E呼喊 {
					说话方式 = 2
				}
				//在游戏中人物的头顶显示说的话
				tx := CreateBuff(100)
				tx.AddInt32(电话.来源.Id)
				tx.AddInt16(0x00C0)
				tx.AddByte(0x00)
				tx.AddByte(说话方式)
				tx.AddStringAndLen(电话.来源.V内容.(*S角色列表).V名字)
				tx.AddStringAndLen(电话.通讯内容)
				//先给自己发送消息
				F地图_发送信息(电话.来源, &S交换数据{
					V发送人: nil,
					V类型:  E交换数据类型_透传数据,
					V内容: S交换角色通讯{
						VCMD:     0x0B,
						VHeadlen: 4,
						V信息:      tx.Buff,
					},
				})
				向周边发送消息(电话.来源, 0x0B, 4, tx.Buff)
				/*{
					//在底部显示文字
					tx := CreateBuff(2 + 4 + len(电话.通讯内容))
					tx.AddInt16(0x00BC)
					tx.AddInt32(5)
					tx.AddStringAndLen(电话.通讯内容)
					F地图_发送信息(电话.来源, &S交换数据{
						V发送人: nil,
						V类型:  E交换数据类型_透传数据,
						V内容: S交换角色通讯{
							VCMD:     0x0A,
							VHeadlen: 0,
							V信息:      tx.Buff,
						},
					})
					向周边发送消息(电话.来源, 0x0A, 0, tx.Buff)
				}*/
			case E耳语:
				耳语对象 := 地图_找到指定角色(电话.目标名字)
				if 耳语对象 == nil {
					消息_系统消息(电话.来源, 3, fmt.Sprintf("[%s]角色不存在", 电话.目标名字))
				} else {
					来源角色 := 电话.来源.V内容.(*S角色列表)
					tx := CreateBuff(2 + 1 + len(来源角色.V名字) + len(电话.通讯内容))
					tx.AddInt16(0x00C2)
					tx.AddByte(0x00)
					tx.AddStringAndLen(来源角色.V名字)
					tx.AddStringAndLen(电话.通讯内容)
					F地图_发送信息(耳语对象, &S交换数据{
						V发送人: nil, //由于是指定人的话，需要判断是否在周边，所以这里必须是系统
						V类型:  E交换数据类型_透传数据,
						V内容: S交换角色通讯{
							VCMD:     0x0A,
							VHeadlen: 0,
							V信息:      tx.Buff,
						},
					})
				}
			case E行会发言:
				角色 := 电话.来源.V内容.(*S角色列表)
				tx := CreateBuff(2 + 4 + 4 + len(电话.通讯内容))
				tx.AddInt16(0x0078)
				tx.AddStringAndLen(角色.V行会名)
				tx.AddStringAndLen(角色.V名字)
				tx.AddStringAndLen(电话.通讯内容)

				//domain := fmt.Sprintf("[V行会名,=,'%s']", 角色.V行会名)
				var 成员列表 []*S角色列表
				if err := db.Where("行会名=?", 角色.V行会名).Find(&成员列表); err != nil {
					消息_系统消息(电话.来源, 3, "获取行会会长信息出错!"+err.Error())
				}
				for _, 会员 := range 成员列表 {
					会员内容 := 地图_找到指定角色(会员.V名字)
					if 会员内容 == nil {
						continue
					}
					F地图_发送信息(会员内容, &S交换数据{
						V发送人: nil,
						V类型:  E交换数据类型_透传数据,
						V内容: S交换角色通讯{
							VCMD:     0x0A,
							VHeadlen: 0,
							V信息:      tx.Buff,
						},
					})
				}

			case E系统消息:
				tx := CreateBuff(2 + 4 + 4 + len(电话.通讯内容))
				tx.AddInt16(0xBC)
				tx.AddInt32(03)
				tx.AddStringAndLen(电话.通讯内容)
				m_RunTime.Range(func(key, value interface{}) bool {
					value.(*RunTime).AddHeadSend10(0x0A, [][]byte{{}, tx.Buff})
					return true
				})
			case E频道:
				tx := CreateBuff(100)
				tx.AddInt16(0x0038)
				tx.AddByte(0x00) //0灰色字体  1：蓝色字体
				tx.AddStringAndLen(电话.来源.V内容.(*S角色列表).V名字)
				tx.AddStringAndLen(电话.频道)
				tx.AddStringAndLen(电话.通讯内容)

				if 频道列表t, ok := m_频道列表.Load(电话.频道); ok == true {
					频道列表 := 频道列表t.(*sync.Map)
					频道列表.Range(func(key, value interface{}) bool {
						F地图_发送信息(value.(*StructMap), &S交换数据{
							V类型: E交换数据类型_透传数据,
							V内容: S交换角色通讯{
								VCMD:     0x0A,
								VHeadlen: 0,
								V信息:      tx.Buff,
							},
						})
						return true
					})
				}
			case E挂载频道:
				var 频道列表 sync.Map
				频道列表.Store(电话.来源.Id, 电话.来源)
				if 列表, ok := m_频道列表.LoadOrStore(电话.频道, &频道列表); ok == true {
					列表.(*sync.Map).Store(电话.来源.Id, 电话.来源)
				}
			case E撤销频道:
				if 频道列表, ok := m_频道列表.Load(电话.频道); ok == true {
					频道列表.(*sync.Map).Delete(电话.来源.Id)
				}
			}
		}
	}
}
